#include "StdAfx.h"
#include "VectorLayer.h"
#include "ogr_srs_api.h"
#include "cpl_conv.h"
#include "sqlite3.h"
#include "drawer.h"

CVectorLayer::CVectorLayer()
{
	//mSourceCRS = OSRNewSpatialReference( NULL );
    //mDestCRS = OSRNewSpatialReference( NULL );
	//setDataProvider(dataProvider);
	//setCoordinate();
}

CVectorLayer::~CVectorLayer()
{
	//if (mOgrDataSource)
	//{
	//	OGR_DS_Destroy( mOgrDataSource );
	//}
	//OSRDestroySpatialReference(mSourceCRS);

 //   OSRDestroySpatialReference(mDestCRS);
	if (m_geometries)
	{
		for (int ii = 0; ii < m_geometries->GetCount(); ii++)
		{
			delete m_geometries->GetAt(ii);
		}
		m_geometries->RemoveAll();
		delete m_geometries;
	}
}

//void CVectorLayer::setDataProvider(  CString & provider )
//{
//	if ( 0 >= OGRGetDriverCount() )
//	{
//		OGRRegisterAll();
//	}
//	mOgrDataSource = OGROpen((LPSTR)(LPCTSTR)m_layerPath,TRUE, &mOgrDriver);	
//}

//void CVectorLayer::loadFields()
//{
//	if (mOgrDataSource)
//	{
//		mOgrLayer = OGR_DS_GetLayer(mOgrDataSource,0);
//	}
//
//	mEnvelope = (OGREnvelope*)calloc(sizeof(OGREnvelope),1);
//	OGR_L_GetExtent(mOgrLayer, mEnvelope, TRUE);
//	OGRGeometryDefnH GeometryDef = OGR_L_GetLayerDefn(mOgrLayer);
//	if (GeometryDef)
//	{
//		mGeomType = OGR_FD_GetGeomType(GeometryDef);
//	}
//	mGeometryCount = OGR_L_GetGeometryCount(mOgrLayer,TRUE);
//	//the attribute fields need to be read again when the encoding changes
//	mAttributeFields.clear();
//	OGRGeometryDefnH fdef = OGR_L_GetLayerDefn( ogrLayer );
//	if ( fdef )
//	{
//		geomType = OGR_FD_GetGeomType( fdef );
//
//		//Some ogr drivers (e.g. GML) are not able to determine the geometry type of a layer like this.
//		//In such cases, we examine the first Geometry
//		if ( geomType == wkbUnknown )
//		{
//			OGR_L_ResetReading( ogrLayer );
//			OGRGeometryH firstGeometry = OGR_L_GetNextGeometry( ogrLayer );
//			if ( firstGeometry )
//			{
//				OGRGeometryH firstGeometry = OGR_F_GetGeometryRef( firstGeometry );
//				if ( firstGeometry )
//				{
//					geomType = OGR_G_GetGeometryType( firstGeometry );
//				}
//				OGR_F_Destroy( firstGeometry );
//			}
//			OGR_L_ResetReading( ogrLayer );
//		}
//
//		for ( int i = 0; i < OGR_FD_GetFieldCount( fdef ); ++i )
//		{
//			OGRFieldDefnH fldDef = OGR_FD_GetFieldDefn( fdef, i );
//			OGRFieldType ogrType = OGR_Fld_GetType( fldDef );
//			QVariant::Type varType;
//			switch ( ogrType )
//			{
//			case OFTInteger: varType = QVariant::Int; break;
//			case OFTReal: varType = QVariant::Double; break;
//				// unsupported in OGR 1.3
//				//case OFTDateTime: varType = QVariant::DateTime; break;
//#if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1400
//			case OFTString: varType = QVariant::String; break;
//#endif
//			default: varType = QVariant::String; // other unsupported, leave it as a string
//			}
//
//			mAttributeFields.insert(
//				i, QgsField(
//				mEncoding->toUnicode( OGR_Fld_GetNameRef( fldDef ) ), varType,
//				mEncoding->toUnicode( OGR_GetFieldTypeName( ogrType ) ),
//				OGR_Fld_GetWidth( fldDef ),
//				OGR_Fld_GetPrecision( fldDef ) ) );
//		}
//	}
//}

bool CVectorLayer::draw(CDrawer* pDrawer)
{
	drawGeometrys(pDrawer);
	return true;
}

//void CVectorLayer::setCoordinate()
//{
//	if (mOgrDriver)
//	{
//		const char* driverName = OGR_Dr_GetName(mOgrDriver);
//		if (0 == StrCmp((LPCSTR)driverName,"ESRI Shapefile"))
//		{
//			int index = m_layerPath.ReverseFind('.');
//			CString layerPathWithoutExt = m_layerPath.Left(index);
//			CString layerProjFile = layerPathWithoutExt;
//			layerProjFile += ".qpj";
//			CFile projFile;
//			if (projFile.Open(layerProjFile,CFile::modeRead))
//			{
//				char* wktString;
//				projFile.Read(wktString, projFile.GetLength());
//				projFile.Close();
//				createCoordinateFromWkt(wktString,mSourceCRS);
//				return;
//			}
//		}
//	}
//
//	OGRSpatialReferenceH sptialRef = OGR_L_GetSpatialRef(mOgrLayer);
//	if (sptialRef == NULL)
//	{
//		return;
//	}
//	else
//	{
//		char *pszWkt = NULL;
//		OSRExportToWkt( sptialRef, &pszWkt );		
//		createCoordinateFromWkt(pszWkt,mSourceCRS);
//		OGRFree( pszWkt );
//	}
//}

//bool CVectorLayer::createCoordinateFromWkt(char* theWkt,OGRSpatialReferenceH crs)
//{
//	if (theWkt == NULL || 1 == strlen(theWkt))
//	{
//		return false;
//	}
//
//	OGRErr myInputResult = OSRImportFromWkt( crs, &theWkt);
//
//	// create the proj4 structs needed for transforming
//	char *proj4src = NULL;
//	OSRExportToProj4( crs, &proj4src );
//
//	//now that we have the proj4string, delegate to createFromProj4String so
//	// that we can try to fill in the remaining class members...
//	//create from Proj will set the isValidFlag
//	createCoordinateFromDb(mSrsDbFilePath,"parameters",proj4src,mSourceCRS);
//	CPLFree( proj4src );
//}

//bool CVectorLayer::createCoordinateFromDb(CString dbFile, char* field, char* value, OGRSpatialReferenceH crs)
//{
//	sqlite3 *database;
//	sqlite3_stmt *preparedStatement;
//	const char *tail;
//	CString sqlStr;
//	CString projStr(value);
//    projStr = projStr.Trim();
//	// please trim projStr, otherwise can't find anything from database: sqlite3_prepare return SQLITE_DONE
//    sqlStr.Format("select srs_id,description,projection_acronym,ellipsoid_acronym,parameters,srid,epsg,is_geo from tbl_srs where %s='%s'",field,projStr);
//	openDB(mSrsDbFilePath, &database);
//	int iResult = sqlite3_prepare(database,(LPCSTR)sqlStr, sqlStr.GetLength(),&preparedStatement,&tail);
//	int sqliteStep = sqlite3_step(preparedStatement);
//	if (iResult == SQLITE_OK &&  sqliteStep == SQLITE_ROW)
//	{
//		int columnCount = sqlite3_column_count(preparedStatement);
//		CString columnName, columnValue;
//		for (int ii = 0; ii < columnCount; ii++)
//		{
//			columnName = sqlite3_column_name(preparedStatement,ii);
//			columnValue = sqlite3_column_text(preparedStatement,ii);
//			mFields.SetAt(columnName,columnValue);
//		}
//	}
//	sqlite3_finalize(preparedStatement);
//	sqlite3_close(database);
//
//	if (mFields.IsEmpty())
//	{
//		return false;
//	}
//
//	OSRDestroySpatialReference(crs);
//	crs = OSRNewSpatialReference(NULL);
//    CString parameters;
//    mFields.Lookup("parameters",parameters);
//	if (OSRImportFromProj4(crs,parameters) != OGRERR_NONE)
//	{
//		return false;
//	}
//
//	setMapUnit();
//	return true;
//}
//
//bool CVectorLayer::openDB(CString databasePath, sqlite3 **db)
//{	
//	return sqlite3_open((LPCSTR)databasePath, db);
//}
//
//bool CVectorLayer::createFromSrsId(CString srsId)
//{
//	return true;
//}

//bool CVectorLayer::setMapUnit()
//{
//	mUnitType = UnitType::UnknownUnit;
//	// Of interest to us is that this call adds in a unit parameter if
//	// one doesn't already exist.
//	OSRFixup(mSourceCRS);
//
//	if (OSRIsProjected(mSourceCRS))
//	{
//
//	}
//	else
//	{
//		char* unitName;
//		OSRGetAngularUnits(mSourceCRS, &unitName);
//		if (0 == strcmp(unitName, "degree"))
//		{
//			mUnitType = UnitType::Degrees;
//		}
//	}
//
//	return true;
//}

void CVectorLayer::drawGeometrys(CDrawer* pDrawer)
{
	for (int ii = 0; ii < m_geometryCount; ii++)
	{
		CGeometry* pGeometry = m_geometries->GetAt(ii);
		if (pGeometry)
		{
			pGeometry->draw(pDrawer);
		}		
	}
}

void CVectorLayer::drawGeometry(CDrawer* pDrawer, OGRFeatureH feature)
{
	OGRGeometryH ogrGeom = OGR_F_GetGeometryRef(feature);
	if (NULL == ogrGeom)
	{
		return;
	}

	OGRwkbGeometryType geomType = OGR_G_GetGeometryType(ogrGeom);

	unsigned char* wkbStr = new unsigned char[OGR_G_WkbSize(ogrGeom)];
	OGR_G_ExportToWkb(ogrGeom, (OGRwkbByteOrder)(( htonl( 1 ) == 1 ) ? 0 : 1),wkbStr);
	switch ( geomType )
	{
		case OGRwkbGeometryType::wkbPoint:
		case OGRwkbGeometryType::wkbPoint25D:
			{
				double x = *(( double * )( wkbStr + 5 ) );
				double y = *(( double * )( wkbStr + 5 + sizeof( double ) ) );
				pDrawer->drawPoint(x,y);
			}
		default:break;
	}
}
